package com.monkey.util.order;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.monkey.core.ErrorCode;
import com.monkey.generator.dao.TWKCOrderMapper;
import com.monkey.generator.model.TWKCOrder;
import com.monkey.generator.model.TWKCOrderExample;
import com.monkey.model.user.User;
import com.monkey.service.UserService;
import com.monkey.util.WebConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.monkey.service.MonkeyService.MONKEY_STATUS_NORMAL;
import static com.monkey.service.UserService.ACTION_CHARGE;

/**
 * desc:
 * auth: chenxiaobin
 * data: 2018/2/4.
 */
@Component
public class WKCOrderUtil {
    private static Logger logger = LoggerFactory.getLogger(WKCOrderUtil.class);
    private static final String URL = "https://walletapi.onethingpcs.com/getTransactionRecords";
    private RestTemplate restTemplate = new RestTemplate();
    private int total;

    @Resource
    private UserService userService = null;

    @Resource
    private TWKCOrderMapper wkcOrderMapper = null;

    @Resource
    private WebConfig webConfig = null;

    public void init() {
        TWKCOrderExample example = new TWKCOrderExample();
        total = (int) wkcOrderMapper.countByExample(example);
    }

    public void handle() {
        String wallet = webConfig.get("wkc.wallet");
        int num = webConfig.getInt("wkc.num");
        Map<String, Object> ret = getList(wallet, 1, num);
        if (null == ret) {
            logger.info("wkc handle get first error");
            return;
        }

        int total = (int) ret.get("totalnum");
        if (total == this.total) {
            logger.info("wkc handle new:0");
            return;
        }

        // 获取所有数据
        if ((total - this.total) > num) {
            List<Map<String, Object>> list = (List<Map<String, Object>>) ret.get("result");
            if (null == list) {
                logger.info("wkc handle get first result error");
                return;
            }

            int size = total - this.total - num;
            int n = size / num;
            if (0 != size % num) {
                ++n;
            }
            for (int i = 0; i < n; ++i) {
                Map<String, Object> ret1 = getList(wallet, i + 2, num);
                if (null == ret1) {
                    logger.info("wkc handle get list error:{}, {}", i + 2, num);
                    return;
                }

                List<Map<String, Object>> list1 = (List<Map<String, Object>>) ret1.get("result");
                if (null == list1) {
                    logger.info("wkc handle get list result error:{}, {}", i + 2, num);
                    return;
                }
                list.addAll(list1);
            }

            size = total - this.total;
            for (int i = size - 1; i >= 0; --i) {
                updateMoney(list.get(i));
            }
        } else {
            List<Map<String, Object>> list = (List<Map<String, Object>>) ret.get("result");
            if (null == list) {
                logger.info("wkc handle get result error");
                return;
            }

            int size = total - this.total;
            for (int i = size - 1; i >= 0; --i) {
                updateMoney(list.get(i));
            }
        }

        this.total = total;
    }

    private void updateMoney(Map<String, Object> item) {
        BigInteger base = new BigInteger("10000000000", 10);
        String amountS = (String) item.get("amount");
        BigInteger amount = new BigInteger(amountS.substring(2), 16);
        amount = amount.divide(base);
        BigDecimal amountDec = new BigDecimal(amount.floatValue() / 100000000);

        String costS = (String) item.get("cost");
        BigInteger cost = new BigInteger(costS.substring(2), 16);
        cost = cost.divide(base);
        BigDecimal costDec = new BigDecimal(cost.floatValue() / 100000000);

        long time = Long.valueOf((String) item.get("timestamp")) * 1000;

        TWKCOrder order = new TWKCOrder();
        order.setOrderid((String) item.get("order_id"));
        order.setType((int) item.get("type"));
        order.setWallet((String) item.get("tradeAccount"));
        order.setAmonut(amountDec);
        order.setCost(costDec);
        order.setHash((String) item.get("hash"));
        order.setExec(false);
        order.setCreatetime(new Date(time));

        // 只处理入账
        float money = order.getAmonut().floatValue();
        if (order.getType() == 1 && money > 0) {
            User user = userService.getUserByWallet(order.getWallet());
            if (null == user) {
                logger.info("wkc handle update money user error:{}, {}", order.getHash(), order.getWallet());
            } else {
                if (ErrorCode.SUCCESS != userService.updateUserMoney(user, 0, money, 0, MONKEY_STATUS_NORMAL, ACTION_CHARGE)) {
                    logger.info("wkc handle update money error:{}, {}", user, money);
                } else {
                    order.setExec(true);
                }
            }
        } else {
            order.setExec(true);
        }

        if (0 == wkcOrderMapper.insert(order)) {
            logger.info("wkc handle write db error:{}, {}, {}", order.getOrderid(), order.getWallet(), order.getAmonut());
        }
    }

    private Map<String, Object> getList(String wallet, int offset, int num) {
        List<String> params = new ArrayList<>();
        params.add(wallet);
        params.add("0");
        params.add("0");
        params.add(String.valueOf(offset));
        params.add(String.valueOf(num));

        // 远程调用
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<List<String>> entity = new HttpEntity<>(params, headers);

        // 返回
        try {
            logger.info("wkc get list:{}, {}", offset, num);
            ResponseEntity<String> respEntity = restTemplate.exchange(URL, HttpMethod.POST, entity, String.class);
            if (respEntity.getStatusCode().toString().equals("200")) {
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, Object> ret = objectMapper.readValue(respEntity.getBody(), Map.class);
                logger.info("wkc get list ret:{}", ret);
                return ret;
            }
        } catch (Exception e) {
            logger.error("wkc get list error:{}, {}, {}, {}", wallet, offset, num, e);
        }
        return null;
    }
}
